package test.baojia.act.check;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.testng.Assert;
import test.baojia.act.operation.BsSelectOperation;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class CommonCheck extends Check {

    public enum CHECK_TYPE{
        checkValue ,
        checkText ,
        checkVisable,
        checkSelectOptions,
        checkAttribute,
        checkServerTime,
        checkExists
    };

    private final static DateTimeFormatter TIME_FORMAT_DF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public void run(JSONObject context, WebDriver driver, Properties resource, JSONObject parentContext) throws Exception{
        super.run(context, driver, resource, parentContext);

        final String checkType = context.getString("checkType");

        if(CHECK_TYPE.checkValue.toString().equals(checkType) ||
                CHECK_TYPE.checkAttribute.toString().equals(checkType)){
            final String byValue = (String) context.get(OPERATION.byValue.toString());
            final String byAttribute =
                    CHECK_TYPE.checkValue.toString().equals(checkType) ?
                            "value" : (String) context.get(OPERATION.byAttribute.toString());
            this.newWebDriverWait(null).until(
                    ExpectedConditions.attributeToBe(this.makeBy() , byAttribute , byValue)
            );
        }else if(CHECK_TYPE.checkText.toString().equals(checkType)){
            final String byText = context.getString(OPERATION.byText.toString());
            By by = this.makeBy();
            this.newWebDriverWait(null).until(ExpectedConditions.textToBe(by , byText));
        }else if(CHECK_TYPE.checkVisable.toString().equals(checkType)){
            By by = this.makeBy();
            final boolean byVisable = context.getBoolean(OPERATION.byVisable.toString());
            ExpectedCondition condition = byVisable ?
                    ExpectedConditions.visibilityOfElementLocated(by) :
                    ExpectedConditions.invisibilityOfElementLocated(by);
            this.newWebDriverWait(null).until(condition);
        }else if(CHECK_TYPE.checkSelectOptions.toString().equals(checkType)){

            Select select = this.makeSelectWebElement(true);
            List<WebElement> options = select.getOptions();
            List<WebElement> visableOptions = new ArrayList();
            for(WebElement option : options){
                if(!BsSelectOperation.isOptionHide(option)){
                    visableOptions.add(option);
                }
            }

            final JSONArray optionValues = context.getJSONArray(OPERATION.byOptions.toString());
            List<String> values = new ArrayList();
            for(int i = 0; i < optionValues.size() ; i++){
                String value = optionValues.getString(i);
                values.add(value);
            }

            Assert.assertEquals(visableOptions.size() , optionValues.size() , "Option count in page not equals to given count.");

            for(WebElement option : visableOptions){
                String optionValue = option.getAttribute("value");
                Assert.assertTrue(
                        values.contains(optionValue),
                        String.format("Option value '%s' in page not contains in the given." , optionValue)
                );
            }

        }else if(CHECK_TYPE.checkServerTime.toString().equals(checkType)){
            //由于业务服务器时间和测试服务器时间有差异，所以允许差异N分钟。
            String serverTimeString = this.makeWebElement(false).getText();
            if(serverTimeString!=null&&!"".equals(serverTimeString)){
                long div = ChronoUnit.MINUTES.between(LocalDateTime.parse(serverTimeString , TIME_FORMAT_DF), LocalDateTime.now());
                long minuteDiv = Long.valueOf(resource.getProperty("server.time.minute.div"));
                Assert.assertTrue(div <= minuteDiv);
            }else{
                Assert.assertTrue("".equals(serverTimeString));
            }

        }else if(CHECK_TYPE.checkExists.toString().equals(checkType)){
            //由于业务服务器时间和测试服务器时间有差异，所以允许差异N分钟。
            Assert.assertTrue(!this.makeWebElements().isEmpty());
        }else {
            Assert.assertTrue(false , "No one check matched.");
        }
    }
}
